package CertificateAuthority;
import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;

public class CA {
	private static byte DOMAIN_CA = (byte)0;
	private static byte DOMAIN_GOV = (byte)1;
	private static byte DOMAIN_EGOV = (byte)10;
	private static byte DOMAIN_SOCIAL = (byte)11;
	private static byte DOMAIN_COMMON = (byte)12;
	
	/**
	 * @param args
	 * @throws NoSuchAlgorithmException 
	 * @throws NoSuchProviderException 
	 * @throws InvalidKeyException 
	 * @throws SignatureException 
	 * @throws UnsupportedEncodingException 
	 * @throws InvalidKeySpecException 
	 */
	public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, UnsupportedEncodingException, InvalidKeySpecException {
		
		/* Aanmaken van alle certificaten */
//		Calendar c = Calendar.getInstance();
//		c.add(Calendar.YEAR, 5);	//Alle certificaten zijn 5 jaar geldig
		
		//TODO: enum aanmaken met domain ID's !!!!!!!!
//		Cert ca 		=	new Cert(DOMAIN_CA, "CA", "CA", c.getTime());										//Domain, issuer, subject, endDate
//		Cert government = 	new Cert(DOMAIN_GOV, "CA", "Certificate of the government", c.getTime());			//Domain, issuer, subject, endDate
//		Cert social1 	=	new Cert(DOMAIN_SOCIAL, "CA", "First certificate in social domain", c.getTime());	//Domain, issuer, subject, endDate
//		Cert social2 	=	new Cert(DOMAIN_SOCIAL, "CA", "Second certificate in social domain", c.getTime());	//Domain, issuer, subject, endDate
//		Cert eGov1 		=	new Cert(DOMAIN_EGOV, "CA", "First certificate in eGov domain", c.getTime());		//Domain, issuer, subject, endDate
//		Cert eGov2 		=	new Cert(DOMAIN_EGOV, "CA", "Second certificate in eGov domain", c.getTime());		//Domain, issuer, subject, endDate
//		Cert common 	= 	new Cert(DOMAIN_COMMON, "CA", "For common use", c.getTime());
//							//Domain, issuer, subject, endDate

		/* Signen van alle certificaten met de private key van de CA */
		
//		ca.Sign(ca.privateKey);	//self signed
//		government.Sign(ca.privateKey);
//		social1.Sign(ca.privateKey);
//		social2.Sign(ca.privateKey);
//		eGov1.Sign(ca.privateKey);
//		eGov2.Sign(ca.privateKey);
//		common.Sign(ca.privateKey);
		
		
		/* Wegschrijven van de certificaten */
		
//		ca.ExportToFile("secure_files/certificate_ca.cert");
//		government.ExportToFile("secure_files/certificate_government.cert");
//		social1.ExportToFile("secure_files/SP/certificate_social1.cert");
//		social2.ExportToFile("secure_files/SP/certificate_social2.cert");
//		eGov1.ExportToFile("secure_files/SP/certificate_eGov1.cert");
//		eGov2.ExportToFile("secure_files/SP/certificate_eGov2.cert");
//		common.ExportToFile("secure_files/certificate_common.cert");
		
		
		/* Inlezen alle certificaten */
		byte[] ca_bytes = CA.readFile("secure_files/certificate_ca.cert");
		byte[] government_bytes = CA.readFile("secure_files/certificate_government.cert");
		byte[] social1_bytes = CA.readFile("secure_files/SP/certificate_social1.cert");
		byte[] social2_bytes = CA.readFile("secure_files/SP/certificate_social2.cert");
		byte[] eGov1_bytes = CA.readFile("secure_files/SP/certificate_eGov1.cert");
		byte[] eGov2_bytes = CA.readFile("secure_files/SP/certificate_eGov2.cert");
		byte[] common_bytes = CA.readFile("secure_files/certificate_common.cert");
		
		/* Printen en verificatie van alle certificaten */
		
		Cert ca_from_file = Cert.FromByteArray(ca_bytes);
		System.out.println(ca_from_file);
		System.out.println("Verify = " + ca_from_file.Verify(ca_from_file.publicKey));
		
		Cert government_from_file = Cert.FromByteArray(government_bytes);
		System.out.println(government_from_file);
		System.out.println("Verify = " + government_from_file.Verify(ca_from_file.publicKey));		
         
		
		Cert social1_from_file = Cert.FromByteArray(social1_bytes);
		System.out.println(social1_from_file);
		System.out.println("Verify = " + social1_from_file.Verify(ca_from_file.publicKey));
		
		Cert social2_from_file = Cert.FromByteArray(social2_bytes);
		System.out.println(social2_from_file);
		System.out.println("Verify = " + social2_from_file.Verify(ca_from_file.publicKey));
		
		Cert eGov1_from_file = Cert.FromByteArray(eGov1_bytes);
		System.out.println(eGov1_from_file);
		System.out.println("Verify = " + eGov1_from_file.Verify(ca_from_file.publicKey));
		
		Cert eGov2_from_file = Cert.FromByteArray(eGov2_bytes);
		System.out.println(eGov2_from_file);
		System.out.println("Verify = " + eGov2_from_file.Verify(ca_from_file.publicKey));
		
		Cert common_from_file = Cert.FromByteArray(common_bytes);
		System.out.println(common_from_file);
		System.out.println("Verify = " + common_from_file.Verify(ca_from_file.publicKey));   
		
		
		/* Wegschrijven private keys */
		
//		ca.ExportPrivateToFile("secure_files/private_ca.key");
//		government.ExportPrivateToFile("secure_files/private_government.key");
//		social1.ExportPrivateToFile("secure_files/SP/private_social1.key");
//		social2.ExportPrivateToFile("secure_files/SP/private_social2.key");
//		eGov1.ExportPrivateToFile("secure_files/SP/private_eGov1.key");
//		eGov2.ExportPrivateToFile("secure_files/SP/private_eGov2.key");
//		common.ExportPrivateToFile("secure_files/private_common.key");
		
		
		/* Inlezen en printen van alle private keys */
	
		byte[] priv_ca = readFile("secure_files/private_ca.key");
		System.out.println("Private CA: [" + StringFromByteArray(priv_ca) + "]");
		
		byte[] priv_government = readFile("secure_files/private_government.key");
		System.out.println("Private government: [" + StringFromByteArray(priv_government) + "]");
		
		byte[] priv_social1 = readFile("secure_files/SP/private_social1.key");
		System.out.println("Private social1: [" + StringFromByteArray(priv_social1) + "]");
		
		byte[] priv_social2 = readFile("secure_files/SP/private_social2.key");
		System.out.println("Private social2: [" + StringFromByteArray(priv_social2) + "]");
		
		byte[] priv_eGov1 = readFile("secure_files/SP/private_eGov1.key");
		System.out.println("Private eGov1: [" + StringFromByteArray(priv_eGov1) + "]");
		
		byte[] priv_eGov2 = readFile("secure_files/SP/private_eGov2.key");
		System.out.println("Private eGov2: [" + StringFromByteArray(priv_eGov2) + "]");
		
		byte[] priv_common = readFile("secure_files/private_common.key");
		System.out.println("Private common: [" + StringFromByteArray(priv_common) + "]");
		
		
		/* 
		 * Get the private key object 
		 * */
		
		/*EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(priv_common);
        KeyFactory generator = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = generator.generatePrivate(privateKeySpec);
		sun.security.rsa.RSAPrivateCrtKeyImpl pk = (sun.security.rsa.RSAPrivateCrtKeyImpl) privateKey;

         BigInteger bi  = pk.getModulus();
         System.out.println("Modulus: ");
         for (byte b : bi.toByteArray()) {
        	System.out.print("(byte) " + b + ", ");
         }
         
         BigInteger bi2  = pk.getPrivateExponent();
         System.out.println("EXP: ");
         for (byte b : bi2.toByteArray()) {
        	System.out.print("(byte) " +b + ", ");
         }*/
		
		/* 
		 * Get the certificate bytes for card 
		 * */
		/*System.out.print("Certificate: ");
		for(byte b : common_bytes) {
			System.out.print("(byte) " + b+ ",");
		}*/
		
		
		/* 
		 * Get the public key from the ca to put on the card 
		 * */
		/*sun.security.rsa.RSAPublicKeyImpl publicKey = (sun.security.rsa.RSAPublicKeyImpl)common_from_file.publicKey;
		byte[] modulusBytes = publicKey.getModulus().toByteArray();
		byte[] exponentBytes = publicKey.getPublicExponent().toByteArray();
		
		
		System.out.print("Modulus COMM public key: ");
		for(byte b : modulusBytes) {
			System.out.print("(byte) " + b+ ",");
		}

		System.out.print("\nExponent COMM public key: ");
		for(byte b: exponentBytes) {
			System.out.print("(byte) " + b + ",");
		}
		
		System.out.println("\n");*/
		
		//System.out.println("Modulus public key ca from bytes: " + new BigInteger(modulusBytes));
		//System.out.println("Exponent public key ca from bytes: " + new BigInteger(exponentBytes));
		
		//System.out.println("\n" + publicKey.toString());
		/*byte[] foto = readFile("Naamloos.bmp");
		System.out.print("foto: length = " + foto.length);
		for(byte b: foto) {
			System.out.print("(byte) " + b + ",");
		}*/
		
		
	}
	
	public static byte[] readFile(String filename) {
		File file = new File(filename);
		byte[] fileContent = null;
		try {
			FileInputStream myCert = new FileInputStream(filename);
			fileContent = new byte[(int)file.length()];
			myCert.read(fileContent);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return fileContent;
	}
	
	public static String StringFromByteArray(byte[] data) {
		StringBuffer buff = new StringBuffer();
		for(int i=0; i<data.length; i++) {
			buff.append(Integer.toHexString(data[i]));
		}
		return buff.toString();
	}
}
